package com.chidopi.market.aa.service.impl;

import java.util.List;

import net.sf.navigator.menu.MenuComponent;
import net.sf.navigator.menu.MenuRepository;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.chidopi.cdf.service.IBaseService;
import com.chidopi.cdf.tag.ITagDao;
import com.chidopi.market.aa.domain.Accounts;
import com.chidopi.market.aa.domain.Functions;
import com.chidopi.market.aa.domain.Roles;
import com.chidopi.market.aa.domain.UserDetailsImpl;
import com.chidopi.market.aa.service.IPermissionService;


/**
 * @author Jemmy
 *
 */

public class PermissionServiceImpl implements
		IPermissionService, ITagDao {
	private static Logger logger = LoggerFactory.getLogger(PermissionServiceImpl.class);
	private static final String sqlRootWhere =
		"parent_id is null and enable_flag='Y' and id in (" +
		"select a.function_id from role2function a, account2role b, accounts c, roles d " +
		"where a.role_id=b.role_id and b.account_id=c.id and c.username=? " +
		"and b.role_id=d.id and d.enable_flag='Y') order by DISPLAY_ORDER ";
	private static final String sqlWhere =
		"parent_id = ? and enable_flag='Y' and id in (" +
		"select a.function_id from role2function a, account2role b, accounts c, roles d " +
		"where a.role_id=b.role_id and b.account_id=c.id and c.username=? " +
		"and b.role_id=d.id and d.enable_flag='Y') order by DISPLAY_ORDER ";
	
	private static final String sqlOnlyPassWhere =
		"functionname='密碼管理' and enable_flag='Y' and id in (" +
		"select a.function_id from role2function a, account2role b, accounts c, roles d " +
		"where a.role_id=b.role_id and b.account_id=c.id and c.username=? " +
		"and b.role_id=d.id and d.enable_flag='Y') order by DISPLAY_ORDER ";


	private static final String sqlRolesByAccountWhere =
		"enable_flag='Y' and id in ( "+
	    "select a.role_id from account2role a, accounts b "+
		"where a.account_id = b.id and b.username=?) order by ID ";
	
	private static final String sqlRoleByFunctionWhere = 
			"enable_flag='Y' and id in ( "+
		    "select a.role_id from role2function a, functions b "+
			"where a.function_id = b.id and b.url=?) order by ID ";
	
	@Autowired
	@Qualifier("roleService")
	private IBaseService<Roles> roleService;
	
	@Autowired
	@Qualifier("functionService")
	private IBaseService<Functions> functionService;

	@Autowired
	@Qualifier("accountService")
	private IBaseService<Accounts> accountService;

	@Autowired
	@Qualifier("tagDao")
	private ITagDao tagDao;


	public MenuRepository getRepository(
			String username)
		throws Exception
	{
		MenuRepository repository = new MenuRepository();
		List<Functions> list = this.functionService.find(sqlRootWhere, username);
		if (list == null || list.size()==0) {
			logger.info(username + " don't be allow to access any function!!");
			return null;
		}
		this.getMenu(list, repository, username, null);
		return repository;
	}

	@Override
	public MenuRepository getRepositoryOnlyPass(String username)
			throws Exception {
		
		MenuRepository repository = new MenuRepository();
		List<Functions> list = this.functionService.find(sqlOnlyPassWhere, username);
		if (list == null || list.size()==0) {
			logger.info(username + " don't be allow to access any function!!");
			return null;
		}
		this.getMenu(list, repository, username, null);
		return repository;
	}


	/**
	 * @param list
	 * @param repository
	 * @param username
	 * @param pmc
	 * @throws Exception
	 */
	private void getMenu(
			List<Functions> list,
			MenuRepository repository,
			String username,
			MenuComponent pmc)
		throws Exception
	{
		for (Functions function : list) {
			List<Functions> listSub = this.functionService.find(sqlWhere, function.getId(), username);
			MenuComponent mc = new MenuComponent();
			if (pmc != null) mc.setParent(pmc);
			mc.setTitle(function.getFunctionname());
			mc.setName("L" + function.getId());
			mc.setLocation(function.getUrl());
			if (listSub != null && listSub.size() > 0) {
				this.getMenu(listSub, repository, username, mc);
			}
			repository.addMenu(mc);
		}
	}


	public UserDetails loadUserByUsername(
			String username)
		throws Exception
	{
		try {
			List<Accounts> list = this.accountService.find("username=?", username);
			if (list == null || list.size()==0) {
				logger.info(username + " don't exist in DB!!");
				throw new UsernameNotFoundException(username + " don't exist in DB!!");
			}
			Accounts account = list.get(0);
			List<Roles> roles = getRolesByUsername(username);
			logger.info("Roles: "+roles.size());
			if(roles != null && roles.size() > 0){
				account.setRoles(roles);
			}
			UserDetails user = new UserDetailsImpl(account);
			return user;
		} catch (UsernameNotFoundException eunf) {
			throw eunf;
		} catch (Exception e) {
			logger.warn("AccountService", e);
			throw e;
		}
	}

	public String getCSS(Object username, Object itemID) {
		return this.tagDao.getCSS(username, itemID);
	}

	@Override
	public List<Roles> getRolesByUsername(String username) throws Exception {
		List<Roles> roles = roleService.find(sqlRolesByAccountWhere, username);
		return roles;
	}
	
	@Override
	public List<Roles> getRolesByFunctionUrl(String url) throws Exception{
		List<Roles> roles = roleService.find(sqlRoleByFunctionWhere, url);
		return roles;
	}
	
}
